package com.staginfo.segs.common;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;

import com.staginfo.segs.util.Logs;
import com.staginfo.segs.util.SettingUtils;

import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.ksoap2.transport.ServiceConnectionSE;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.SocketTimeoutException;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 异步API请求
 * Created by Administrator on 2016/7/7 0007.
 */
public class ApiAsyncTask extends AsyncTask<Void,Void,Object> {
    private static final String TAG="ApiAsyncTask";
    //session失效
    public static final int SESSION_INVALID = 700;
    // 超时（网络）异常
    public static final int TIMEOUT_ERROR = 600;
    // 业务异常
    public static final int BUSSINESS_ERROR = 610;
    // 225 请求的数据不存在
    public static final int SC_DATA_NOT_EXIST = 225;
    // 232 非法回复内容
    public static final int SC_ILLEGAL_COMMENT = 232;
    // 421 请求头参数为空或参数不完整（User-Agent等）
    public static final int SC_ILLEGAL_USER_AGENT = 421;
    // 422 请求xml解析错误
    public static final int SC_XML_ERROR = 422;
    // 423 请求xml中参数缺失或参数类型错误
    public static final int SC_XML_PARAMS_ERROR = 423;
    // 427 请求解密或解码错误
    public static final int SC_ENCODE_ERROR = 427;
    //428 没有请求权限
    public static final int DOWNLOAD_STATUS_NOPERMISSION = 428;

    private int requestAction;
    private Object paramter;
    private Context context;
    private String requestUrl;
    private String requestMethod;
    private int waitTime = 10000;
    private boolean isGetCookie=false;//如果为真，则须在头部获取cookie信息,如果为假，则须配置cookie信息
    private ApiRequestListener handler;
    private StermApplication app;

    public ApiAsyncTask(Context context, int requestAction, String requestUrl, String requestMethod, Object paramter, ApiRequestListener handler) {
        this(context, requestAction, requestUrl, requestMethod, paramter, handler, false);
    }
    public ApiAsyncTask(Context context, int requestAction, String requestUrl, String requestMethod, Object paramter, ApiRequestListener handler, boolean isGetCookie) {
        this.context = context;
        this.requestAction = requestAction;
        this.requestUrl = requestUrl;
        this.requestMethod = requestMethod;
        this.paramter = paramter;
        this.handler = handler;
        this.isGetCookie=isGetCookie;
//        app = (StermApplication) context.getApplicationContext();
    }
    public ApiAsyncTask(Context context, int requestAction, String requestUrl, String requestMethod, Object paramter, ApiRequestListener handler, int waitTime) {
        this(context, requestAction, requestUrl, requestMethod, paramter, handler, false);
        this.waitTime=waitTime;
    }

    private Object httpPost(){
        Logs.d(TAG,"method:"+requestMethod+":start:"+System.currentTimeMillis());
        SoapObject request=new SoapObject(Constants.WEB_NAMESPACE,requestMethod);

        if(paramter!=null){
            LinkedHashMap<String,String> requestParams= (LinkedHashMap<String, String>) paramter;
            Iterator<Map.Entry<String,String>> paramIterator=requestParams.entrySet().iterator();
            while (paramIterator.hasNext()){
                Map.Entry<String,String> entry=paramIterator.next();
                if(entry.getKey()!=null && entry.getValue()!=null){
                    request.addProperty(entry.getKey().toString(),entry.getValue().toString());
                }
            }
        }
        SoapSerializationEnvelope soapEnvelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
        soapEnvelope.bodyOut=request;
        soapEnvelope.setOutputSoapObject(request);
        soapEnvelope.dotNet=true;
        HttpTransportSE transport=new HttpTransportSE(requestUrl,waitTime);
        SoapPrimitive response=null;
        try {
            if(isGetCookie){
                List<HeaderProperty> respHeaders=transport.call("",soapEnvelope,null);
                for(HeaderProperty hp:respHeaders){
                    String key = hp.getKey();
                    if (key != null){
                        if (key.equals("Set-Cookie")){
                            SettingUtils.set(context, Config.CONFIG_COOKIE,hp.getValue());
                        }
                    }
                }
                updateInnerSystemDate(transport);
            }else{
                List<HeaderProperty> headers=new ArrayList<HeaderProperty>();
                HeaderProperty hp=new HeaderProperty(Config.CONFIG_COOKIE,SettingUtils.get(context,Config.CONFIG_COOKIE,""));
                headers.add(hp);
                transport.call("",soapEnvelope,headers);
                updateInnerSystemDate(transport);
            }
            response = (SoapPrimitive) soapEnvelope.getResponse();
        } catch (SocketTimeoutException e){
            e.printStackTrace();
            Logs.d(TAG, e.toString());
            return TIMEOUT_ERROR;
        }catch (XmlPullParserException e) {
            e.printStackTrace();
            Logs.d(TAG, e.toString());
            return SC_XML_ERROR;
        }catch (IOException e) {
            e.printStackTrace();
            Logs.d(TAG, e.toString());
            return BUSSINESS_ERROR;
        }
        Logs.d(TAG,response.toString());
        Logs.d(TAG,"method:"+requestMethod+":end s:"+System.currentTimeMillis());
        return response;
    }
    @Override
    protected Object doInBackground(Void... voids) {
        return httpPost();
    }

    @Override
    protected void onPostExecute(Object response) {

        if(handler==null){
            return;
        }
        if(context instanceof Activity && ((Activity)context).isFinishing()){
            return;
        }
        if(response==null){
            handler.onError(this.requestAction,this.BUSSINESS_ERROR);
            return;
        }else if(response instanceof Integer){
            Integer statusCode= (Integer) response;
            if(!handleResult(statusCode)){
                handler.onError(this.requestAction, (Integer) response);
                return;
            }
        }else if(response.toString().equals("false")){
            handler.onError(this.requestAction,SC_DATA_NOT_EXIST);
            return;
        }else if(response.toString().equals("noPermission")){
            handler.onError(this.requestAction,DOWNLOAD_STATUS_NOPERMISSION);
            return;
        }else if(response.toString().equals("Session Invalid")){
            handler.onError(this.requestAction,SESSION_INVALID);
            return;
        }

        handler.onSuccess(this.requestAction,response);
    }

    /**
     * true则表示已被服务器正常接收
     * @param statusCode
     * @return
     */
    private boolean handleResult(int statusCode){
        return statusCode==200;
    }

    private void updateInnerSystemDate(HttpTransportSE transport){
        ServiceConnectionSE connectionSE = (ServiceConnectionSE) transport.getConnection();
        Class userCla = (Class) connectionSE.getClass();
        Field[] fields = userCla.getDeclaredFields();
        URLConnection connection = null;
        try {
            for(Field field : fields){
                if (field.getName().equals("connection")){
                    field.setAccessible(true);
                    connection = (URLConnection) field.get(connectionSE);
                    break;
                }
            }
        }catch (IllegalAccessException e){
            Logs.d("zxc", "error   "+e.toString());
        }
        if (connection!=null){
            long t = connection.getDate();
            Logs.d("zxc", "net date "+ t + new Date(t).toString());
//            app.setInnerSystemTime(connection.getDate());
        }
    }

    /**
     * 服务器请求回调
     */
    public interface ApiRequestListener{
        void onSuccess(int method, Object obj);
        void onError(int method, int statusCode);
    }
}
